package core.entrance;

import core.algorithm.Algorithm;
import core.controllers.ControlConstantParameters;
import core.controllers.ControlDynamicParameters;
import core.problem.FactoryProblems;
import core.problem.Individual;
import core.problem.Population;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JTextArea;

/**
 *
 * @author 郝国生 HAO Guo-Sheng
 */
public class Connection4SetAndRunning {

    private JTextArea mainTextarea;
    int runTimes;

    public void run() {
        //不需要窗口的running
        Algorithm algorithm = ControlDynamicParameters.currentAlgorithm;
        System.out.println("Begin....\n");
        long startTime = System.currentTimeMillis();
        runTimes = ControlConstantParameters.experimentRunningTime;
        int k = 1;
        for (int j = 0; j < ControlConstantParameters.experimentRunningTime; j++) {
            FactoryProblems.currentProblem.init(FactoryProblems.dimension);
            algorithm.init();
            try {
                this.beginEvolving();
            } catch (CloneNotSupportedException ex) {
                Logger.getLogger(Connection4SetAndRunning.class.getName()).log(Level.SEVERE, null, ex);
            }
            this.outprint(k++, startTime);
        }
        System.out.println("over===========");
    }

    public synchronized StringBuilder beginEvolving() throws CloneNotSupportedException {
        StringBuilder result2Show = new StringBuilder();
        Algorithm algorithm = ControlDynamicParameters.currentAlgorithm;
        int generationNum = 0, evaluationNumber = 0;
        long st = System.currentTimeMillis();
        // Begin the TGA
        Population population = FactoryProblems.currentProblem.generatePopulation();//生成种群;
        population.setIndividuals(population.init(ControlDynamicParameters.populationSize));
        algorithm.onceGetFitness4TEC(population);
        evaluationNumber += population.getIndividuals().size();
        Individual stopFitnessIndividual = ((Individual)population.getIndividuals().get(0)).clone();
        stopFitnessIndividual.getDecisionVariable().setFitness(FactoryProblems.currentProblem.getStopFitness());
        boolean continueEvolve = true;//后面用这个来处理算法是否结束的判断，从而结合多种算法终止条件
        //当再遍历10*populationSize仍然没有新的最优解出现，则结束
        //System.out.println(ControlParameters.currentProblem.getName() + ":  best fitness" + population.getBestIndividual().get(0).getFitness()[0]);
        while (continueEvolve) {
            ControlDynamicParameters.currentAlgorithm.getObserver().saveStatus(generationNum++, population);
            algorithm.operats(population);//在选择算子中执行选择前进行排序
            evaluationNumber += population.getIndividuals().size();
            //记录实验过程
            //algorithm.outputBest((population.getBestIndividual()), generationNum);
            if (((Individual)algorithm.getObserver().getBestIndividuals()
                    .get(algorithm.getObserver().getBestIndividuals().size()-1))
                    .compareTo(stopFitnessIndividual) >= 0 //所有问题都要转换为求最大值的问题
                    || evaluationNumber >= ControlConstantParameters.stopEvaluationNumber) {
                continueEvolve = false;
            }
            result2Show.append(this.outputPopulation(generationNum).toString()).append("\n");
        }
        result2Show.append(FactoryProblems.currentProblem.getName())
                .append(":  best fitness")
                .append(((Individual)algorithm.getObserver().getBestIndividuals()
                        .get(algorithm.getObserver().getBestIndividuals().size()-1))
                        .getDecisionVariable().getFitness()[0])
                .append("\n");
        long et = System.currentTimeMillis();
        //下面记录运行时间
        long t3 = et - st;
        result2Show.append("timesecondcost: ")
                .append((int) t3).append("\n");//算法执行时长
        //记录算法与问题的交互次数，即实验访问个体的次数，相当于历史个体个数
        result2Show.append("evaluationnumber: ").append(evaluationNumber).append("\n");
        result2Show.append("Bestsolution: ")
                .append(((Individual)algorithm.getObserver().getBestIndividuals()
                        .get(algorithm.getObserver().getBestIndividuals().size()-1))
                        .getDecisionVariable().getX())
                .append("\n");
        result2Show.append("Bestfitness: ")
                .append(((Individual)algorithm.getObserver().getBestIndividuals()
                        .get(algorithm.getObserver().getBestIndividuals().size()-1))
                        .getDecisionVariable().getFitnessString())
                .append("\n");
        return result2Show;
    }

    private void outprint(int k, long startTime) {
        System.out.printf("完成第%d次实验", k);
        long consummedTime = System.currentTimeMillis() - startTime;
        System.out.printf("已经运行%d秒，估计还需要%d秒\n", consummedTime / 1000,
                ((consummedTime + 1) * (runTimes - k) / (k * 1000)));//加1的目的是防止出现consummedTime为0的情况
    }

    private StringBuilder outputPopulation(int generationNumber) {
        StringBuilder string2Show = new StringBuilder();
        string2Show.append(generationNumber).append("\t");
        string2Show.append(((Individual)ControlDynamicParameters.currentAlgorithm.getObserver().getBestIndividuals()
                .get(ControlDynamicParameters.currentAlgorithm.getObserver().getBestIndividuals().size()-1))
                .getDecisionVariable().getFitnessString()).append("\t").append("\n");
        return string2Show;
    }

}
